home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
graphic
/
pcxut10.zip
/
PCXUTILS.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-08-08
|
19KB
|
500 lines
/* A few simple conversions for monochrome & 16-color PCX files
PCXUTILS is meant to deal with pcx-files produced by DrawPerfect,
WP Presentations, Harvard Graphics and GhostScript.
Output should be usable for WordPerfect and TeX.
Problems which occur with these programs:
- GhostScript doesn't always produce an even n. of bytes
- Harvard Graphics does something funny with the palette
- WordPerfect and some other programs seem to compute bytes/line from
image width instead of reading it directly from the header
- Many graphics programs can't produce monochrome bitmaps, causing
unnecessarily large filesizes
PCXUTILS does the following:
/i: invert
/m: color to monochrome: every non-white color becomes black;
use this option only when the bitmap has a standard palette
apply successive /i /m /i transformations if you want
to map every non-black color to white
/r: round image size up to even n. of bytes per line
/p+: standardize palette by interpreting existing palette; equivalent to /p
/p-: standardize palette and ignore existing palette
Only the first switch is honored.
Irrespective of options:
- round bytes/line up to even number (irrespective of image size)
- reduce bytes/line to smallest possible number
Compiler: Turbo C++ 3.0
*/
/* standard header files */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <alloc.h>
#include <dos.h>
#include <dir.h>
#include <errno.h>
#define FALSE 0
#define TRUE 1
#define LOBYTE(x) (*(unsigned char *)&(x))
#define HIBYTE(x) (*(((unsigned char *)&(x))+1))
void errexit0 (char *message);
void errexit1 (char *message);
int prcount, swcount, parinx, swinx;
void cmdline(void); /* find command-line switch and parameter */
void helpinfo(void);
void make_palette(void);
/* PCX file header */
typedef struct
{ char manufacturer;
char version;
char encoding;
char bits_per_pixel;
int xmin,ymin;
int xmax,ymax;
int hres,vres;
unsigned char palette[48];
char reserved;
char color_planes;
int bytes_per_line;
int palette_type;
char filler[58];
} PCXHEAD;
PCXHEAD header;
/* The following typedefs and data make it possible to determine
pixel values without actual unpacking */
typedef union
{ unsigned long l;
unsigned char c[4];
} MASK; /* for each colorplane one byte */
typedef MASK MASKARRAY[8];
MASKARRAY masks; /* masks to isolate each pixel for each bit position */
MASKARRAY maskpalette[16]; /* (color code, bit position) -> MASK */
MASKARRAY newpalette[16]; /* (new color code, bit position) -> MASK */
/* available processing options */
enum options { opt_tomono, opt_round, opt_invert, opt_pal_ignore,
opt_pal_arrng, opt_none };
int pr_opt; /* selected processing option */
FILE *in, *out;
/* properties input file: */
int old_bpl; /* old value for bytes_per_line */
int bpl_tot; /* bytes per line times color planes */
int old_width; /* old picture width */
int monoin; /* input file is mono */
int chg_bpl; /* bytes per line requires changing */
int palet_funny; /* palette anomalies; implies !mono && header.version!=3 */
char pcxpath[MAXPATH], oldpath[MAXPATH]; /* full filenames */
char old_pal[48]; /* old palette */
unsigned char *const hpal = (unsigned char *)&header.palette;
/* for easy reference to header palette */
char const std_pal[48] = /* a more or less standard EGA palette */
{ 0x0,0x0,0x0, 0x0,0x0,0x80, 0x0,0x80,0x0, 0x0,0x80,0x80,
0x80,0x0,0x0, 0x80,0x0,0x80, 0x80,0x80,0x0, 0x80,0x80,0x80,
0x40,0x40,0x40, 0x0,0x0,0xff, 0x0,0xff,0x0, 0x0,0xff,0xff,
0xff,0x0,0x0, 0xff,0x0,0xff, 0xff,0xff,0x0, 0xff,0xff,0xff };
typedef unsigned char *LINE;
LINE plane[4]; /* up to 4 bitplanes, yet to be allocated */
unsigned char *pl; /* pointer into plane */
void main (int argc, char *argv[])
{ int c,i,j,k,l;
union { unsigned char ch[2]; unsigned int intg; } endmask;
MASK eachplane; /* one byte from each plane */
MASK thispixel;
cmdline();
if (prcount>1) puts ("Excess command-line parameters ignored");
if (swcount>1) puts ("Excess command-line switches ignored");
/* header input file */
if (prcount<1) helpinfo();
{ char fndrive[MAXDRIVE];
char fndir[MAXDIR];
char fnfile[MAXFILE];
fnsplit
(argv[parinx],(char *)fndrive,(char *)fndir,(char *)fnfile,NULL);
fnmerge (pcxpath,(char *)fndrive,(char *)fndir,(char *)fnfile,".PCX");
fnmerge (oldpath,(char *)fndrive,(char *)fndir,(char *)fnfile,".OLD");
}
in = fopen (pcxpath,"rb");
if (!in) errexit0("Access failure input file");
if (fread((char *)&header,1,sizeof(PCXHEAD),in)!=sizeof(PCXHEAD))
errexit0("Failure to read PCX file");
fclose(in); /* later, we reopen the file as *.old */
if (header.manufacturer!=0x0a) errexit0("Not a PCX file");
if (header.bits_per_pixel!=1) errexit0("Format not supported");
/* this might be changed later on */
if (header.color_planes==1) monoin = TRUE;
else if (header.color_planes==4) monoin = FALSE;
else errexit0("Format not supported");
/* standard palette: 1rst color 0,0,0 last ff,ff,ff; all colors different */
palet_funny=FALSE;
memmove(old_pal,header.palette,48);
if (header.version!=3 && !monoin)
{ for (i=0;i<3;i++) if (header.palette[i]!=0)
{ palet_funny=TRUE; break; }
if (!palet_funny) for (i=45;i<48;i++) if (header.palette[i]!=255)
{ palet_funny=TRUE; break; }
if (!palet_funny) for (i=0;i<48;i+=3) /* entries all different? */
{ for (j=0;j<i;j+=3)
if (old_pal[i]==old_pal[j]
&& old_pal[i+1]==old_pal[j+1]
&& old_pal[i+2]==old_pal[j+2]) { palet_funny=TRUE; break; }
if (palet_funny) break;
}
}
/* image width and bytes_per_line */
old_width=header.xmax-header.xmin+1;
if (old_width<=0 || header.ymax<header.ymin)
errexit0("Error: Picture has zero height or width");
old_bpl = header.bytes_per_line;
chg_bpl = (old_bpl%2) || (old_bpl*8-old_width*header.bits_per_pixel>15);
in = NULL; out = NULL;
/* decode switch; start comparing after first character ('/' or '-') */
pr_opt = opt_none;
if (swcount>0)
{ if (!stricmp(argv[swinx]+1,"r")) pr_opt = opt_round;
else if (!stricmp(argv[swinx]+1,"i")) pr_opt = opt_invert;
else if (!stricmp(argv[swinx]+1,"m")) pr_opt = opt_tomono;
else if (!stricmp(argv[swinx]+1,"p+")||
!stricmp(argv[swinx]+1,"p")) pr_opt = opt_pal_arrng;
else if (!stricmp(argv[swinx]+1,"p-")) pr_opt = opt_pal_ignore;
else helpinfo();
}
/* sort out actions; report to user */
/* comments on header */
if (palet_funny && pr_opt!=opt_pal_ignore && pr_opt!=opt_pal_arrng)
puts("Non-standard palette;\n"
"if results unsatisfactory try a preliminary PCXUTILS /p run");
if (chg_bpl) puts ("Correcting bytes/line");
/* options */
if (pr_opt==opt_tomono)
{ if (monoin) { puts("Bitmap already mono"); pr_opt = opt_none; }
else puts("Converting to monochrome");
}
else if (pr_opt==opt_round)
{ if (old_width*header.bits_per_pixel==8*old_bpl && !chg_bpl)
{ puts("Image width is already rounded to match bytes/line");
pr_opt = opt_none; }
else puts("Rounding image width");
}
else if (pr_opt==opt_invert) puts("Inverting colors");
else if (pr_opt==opt_pal_ignore)
{ if (monoin) { puts("Monochrome bitmap"); pr_opt = opt_none; }
else if (header.version==3)
puts("No palette; bitmap gets standard palette");
else if (!palet_funny) { puts("Palette ok"); pr_opt = opt_none; }
else puts("Bitmap gets standard palette; original palette ignored");
}
else if (pr_opt==opt_pal_arrng)
{ if (monoin) { puts("Monochrome bitmap"); pr_opt = opt_none; }
else if (header.version==3)
{ pr_opt = opt_pal_ignore;
puts("No palette; bitmap gets standard palette");
}
else if (!palet_funny) { puts("Palette ok"); pr_opt = opt_none; }
else puts("Palette will be standardized by rearranging original pal